using System;
using System.Collections.ObjectModel;
using Integrity;

namespace UnitTests
{
  public class Cat : ObservableObject, IIntegrityObject
  {
    public string Name { get; private set; }

    public static readonly ReferencePropertyKey<Person> MasterPropertyKey =
      ForType<Cat>.RegisterReferenceProperty<Person>("Master", p => p.MasterProperty, p => p.PetProperty);
    
    public readonly ReferenceProperty<Person> MasterProperty;

    public Person Master
    {
      get { return MasterProperty.Value; }
      set { MasterProperty.Value = value; }
    }

    public Cat(string name)
    {
      Name = name;
      MasterProperty = MasterPropertyKey.ForInstance(this);
    }

    void IIntegrityObject.OnReleased()
    {
      var released = Released;
      if (released != null) released();
    }
    void IIntegrityObject.OnPropertyChanged(string propertyName)
    {
      OnPropertyChanged(propertyName);
    }

    public event Action Released;
  }
  public class Person : ObservableObject, IIntegrityObject
  {
    public string Name { get; set; }

    public static readonly CollectionPropertyKey<Person> FriendsPropertyKey =
      ForType<Person>.RegisterCollectionProperty<Person>("Friends", p => p.FriendsProperty, p => p.FriendsProperty);
    public static readonly CollectionPropertyKey<Person> ChildrenPropertyKey =
      ForType<Person>.RegisterCollectionProperty<Person>("Children", p => p.ChildrenProperty, p => p.FatherProperty);
    public static readonly ReferencePropertyKey<Person> FatherPropertyKey =
      ForType<Person>.RegisterReferenceProperty<Person>("Father", p => p.FatherProperty, p => p.ChildrenProperty);
    public static readonly ReferencePropertyKey<Cat> PetPropertyKey =
      ForType<Person>.RegisterReferenceProperty<Cat>("Pet", p => p.PetProperty, p => p.MasterProperty, true);

    public readonly CollectionProperty<Person> FriendsProperty;
    public readonly CollectionProperty<Person> ChildrenProperty;
    public readonly ReferenceProperty<Person> FatherProperty;
    public readonly ReferenceProperty<Cat> PetProperty;

    public Person(string name)
    {
      Name = name;
      FriendsProperty = FriendsPropertyKey.ForInstance(this);
      FatherProperty = FatherPropertyKey.ForInstance(this);
      ChildrenProperty = ChildrenPropertyKey.ForInstance(this);
      PetProperty = PetPropertyKey.ForInstance(this);
    }
    public override string ToString()
    {
      return Name;
    }
    public Collection<Person> Friends
    {
      get { return FriendsProperty.Values; }
    }
    public Collection<Person> Children
    {
      get { return ChildrenProperty.Values; }
    }
    public Person Father
    {
      get { return FatherProperty.Value; }
      set { FatherProperty.Value = value; }
    }
    public Cat Pet
    {
      get { return PetProperty.Value; }
      set { PetProperty.Value = value; }
    }

    void IIntegrityObject.OnReleased()
    {
      var released = Released;
      if (released != null) released();
    }
    void IIntegrityObject.OnPropertyChanged(string propertyName)
    {
      OnPropertyChanged(propertyName);
    }

    public event Action Released;
  }
}